use std::{borrow::Cow, fmt::Display, iter::Peekable};

use log::debug;

use crate::c::ExprC;
use crate::item::Call;
use crate::item::Enum;
use crate::item::Expr;
use crate::item::IfBranch;
use crate::item::IfExpr;
use crate::item::Switch;
use crate::item::SwitchBranch;
use crate::item::Union;
use crate::item::WithComment;
use crate::item::{ExprPos, Func, Let, Stat, StatPos, Struct, Type, VarDecl};
use crate::lexer::CompareOperator;
use crate::{
    char_seq::Pos,
    lexer::{Token, TokenPos},
};

type CowStr = Cow<'static, str>;

pub struct Parser<Iter: Iterator<Item = TokenPos>> {
    iter: Peekable<Iter>,
}

// Name of "main function" of makec generated code.
pub const MC_MAIN_FUNC: &'static str = "mc__main";

#[derive(Debug)]
pub enum Error {
    Eof,
    ArgumentCount {
        pos: Pos,
        found: usize,
        expect: usize,
    },
    Type {
        pos: Pos,
        found: Type,
        expect: Type,
    },
    NotCallable {
        pos: Pos,
        name: CowStr,
        ty: Type,
    },
    CanNotDref {
        pos: Pos,
        ty: Type,
    },
    Syntax {
        error: String,
        pos: Pos,
    },
    UnexpectedComment {
        pos_desc: CowStr,
        pos: Pos,
    },
    DuplicateName {
        name: CowStr,
        pos: Pos,
    },
}

impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Error::Eof => write!(f, "reach EOF"),
            Error::Syntax { error: err, pos } => {
                write!(f, "{pos} syntax error: {err}",)
            }
            Error::UnexpectedComment { pos_desc, pos } => {
                write!(f, "{pos} unexpected comment before `{pos_desc}'",)
            }
            Error::ArgumentCount { pos, found, expect } => {
                write!(
                    f,
                    "{pos} argument count error, expect: {expect}, found: {found}",
                )
            }
            Error::Type {
                found: found_ty,
                expect: expect_ty,
                pos,
            } => {
                write!(
                    f,
                    "{pos} type error, expect: `{expect_ty}', found: `{found_ty}'",
                )
            }
            Error::NotCallable { pos, name, ty } => {
                write!(f, "{pos}: variable {name} with type {ty} is not callable")
            }
            Error::CanNotDref { ty, pos } => {
                write!(f, "{pos} can't deref variable with type {ty}")
            }
            Error::DuplicateName { name, pos } => {
                write!(f, "{pos} duplicated name `{name}'")
            }
        }
    }
}

impl std::error::Error for Error {}

pub fn syntax_error<S: Into<String>>(message: S, pos: Pos) -> Error {
    Error::Syntax {
        error: message.into(),
        pos,
    }
}

impl<Iter: Iterator<Item = TokenPos>> Parser<Iter> {
    /// Parse expression at top of token stream. Return None if reach end
    /// of token stream.
    pub fn parse_expr(&mut self) -> Result<ExprPos, Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;
        let pos = token.pos.clone();

        let expr = match token.token {
            Token::Error(err) => return Err(Error::Syntax { error: err, pos }),

            // Literals
            Token::Int(i) => Expr::Int(i),
            Token::UInt(i) => Expr::UInt(i),
            Token::I32(i) => Expr::I32(i),
            Token::U32(i) => Expr::U32(i),
            Token::I64(i) => Expr::I64(i),
            Token::U64(i) => Expr::U64(i),
            Token::String(s) => Expr::String(s),
            Token::Boolean(b) => Expr::Boolean(b),
            Token::Char(c) => Expr::Char(c),
            Token::Null => Expr::Null,

            Token::Identifier(name) => {
                if let Some(TokenPos {
                    token: Token::DColon,
                    pos: _,
                }) = self.iter.peek()
                {
                    self.iter.next();

                    let (variant, _) = self.parse_ident()?;

                    Expr::EnumGet { name, variant }
                } else {
                    Expr::Variable(name)
                }
            }
            Token::Enum => {
                self.expect_dot()?;

                let (name, _) = self.parse_ident()?;

                self.expect_dot()?;

                let (variant, _) = self.parse_ident()?;

                Expr::EnumGet { variant, name }
            }
            Token::Lpare => self.parse_s_expr()?,
            _ => {
                return Err(Error::Syntax {
                    error: format!("can't parse expression starts from {:?}", token.token),
                    pos: token.pos,
                })
            }
        };

        let mut expr_pos = ExprPos {
            expr,
            pos,
            ty: Type::Unknown,
        };

        // Parse field EXPR.name, EXPR->name and EXPR[INDEX].

        loop {
            match self.iter.peek() {
                // EXPR.name
                Some(TokenPos {
                    token: Token::Dot,
                    pos: _,
                }) => {
                    expr_pos = self.parse_get(expr_pos)?;
                }
                // EXPR&
                Some(TokenPos {
                    token: Token::Ampersand,
                    pos,
                }) => {
                    let pos = pos.clone();
                    self.iter.next();
                    expr_pos = ExprPos::new(Expr::TakeAddr(Box::new(expr_pos)), pos)
                }
                // EXPR*
                Some(TokenPos {
                    token: Token::Star,
                    pos,
                }) => {
                    let pos = pos.clone();
                    self.iter.next();
                    expr_pos = ExprPos::new(Expr::Dref(Box::new(expr_pos)), pos)
                }
                // EXPR[INDEX]
                Some(TokenPos {
                    token: Token::Lsquace,
                    pos: _,
                }) => {
                    expr_pos = self.parse_take(expr_pos)?;
                }
                _ => break,
            }
        }

        self.try_take_child(&mut expr_pos)?;

        Ok(expr_pos)
    }

    fn try_take_child(&mut self, expr_pos: &mut ExprPos) -> Result<(), Error> {
        match &mut expr_pos.expr {
            Expr::Variable(name) => {
                if name == "_" {
                    if let Some(TokenPos {
                        token: Token::Child,
                        pos: _,
                    }) = self.iter.peek()
                    {
                        self.iter.next();
                        *expr_pos = self.parse_expr()?;
                    };
                }
            }
            Expr::Not { cond } => {
                self.try_take_child(cond)?;
            }
            Expr::Or { head, rest } => {
                self.try_take_child(head)?;
                self.try_take_child_in_args(rest)?;
            }
            Expr::And { head, rest } => {
                self.try_take_child(head)?;
                self.try_take_child_in_args(rest)?;
            }
            Expr::Cast { expr, .. } => {
                self.try_take_child(expr)?;
            }
            Expr::Compare { lhs, rhs, .. } => {
                self.try_take_child(lhs)?;
                self.try_take_child(rhs)?;
            }
            Expr::Compute { head, rest, .. } => {
                self.try_take_child(head)?;
                self.try_take_child_in_args(rest)?;
            }
            Expr::TakeAddr(expr) => {
                self.try_take_child(expr)?;
            }
            Expr::Take { expr, index } => {
                self.try_take_child(&mut *expr)?;
                self.try_take_child(&mut *index)?;
            }
            Expr::Get { expr, .. } => {
                self.try_take_child(&mut *expr)?;
            }
            Expr::Call(Call { args, .. }) => {
                self.try_take_child_in_args(args)?;
            }
            _ => (),
        };

        Ok(())
    }

    fn parse_get(&mut self, expr_pos: ExprPos) -> Result<ExprPos, Error> {
        self.iter.next(); // .

        let field = self.iter.next().ok_or(Error::Eof)?;

        let result = match field.token {
            // expr.(func a)
            Token::Lpare => {
                let (func, func_pos) = self.parse_ident()?;

                let mut args = vec![expr_pos];
                args.extend(self.parse_exprs_until_rpare()?.into_iter());

                ExprPos::new(
                    Expr::Call(Call {
                        is_macro: false,
                        is_method: true,
                        func,
                        args,
                    }),
                    func_pos,
                )
            }
            // expr.<name>
            Token::Identifier(name) => ExprPos::new(
                Expr::Get {
                    expr: Box::new(expr_pos),
                    name,
                },
                field.pos,
            ),
            _ => {
                return Err(syntax_error(
                    format!(
                        "expect identifier, '*' or '&' after dot, find: {:?}",
                        field.token
                    ),
                    field.pos,
                ))
            }
        };

        Ok(result)
    }

    fn parse_take(&mut self, expr_pos: ExprPos) -> Result<ExprPos, Error> {
        self.iter.next();
        let index = self.parse_expr()?;
        let index_pos = index.pos.clone();
        self.expect_rsquace()?;

        Ok(ExprPos {
            expr: Expr::Take {
                expr: Box::new(expr_pos),
                index: Box::new(index),
            },
            pos: index_pos,
            ty: Type::Unknown,
        })
    }

    fn try_take_child_in_args(&mut self, args: &mut Vec<ExprPos>) -> Result<(), Error> {
        for arg in args {
            self.try_take_child(arg)?;
        }
        Ok(())
    }

    pub fn parse_stat(&mut self) -> Result<StatPos, Error> {
        let (document, _) = self.parse_comment();

        let public = self
            .iter
            .next_if(|token| {
                matches!(
                    token,
                    TokenPos {
                        token: Token::Pub,
                        pos: _
                    }
                )
            })
            .is_some();

        let token = self.iter.peek().ok_or(Error::Eof)?;
        let head_pos = token.pos.clone();

        let stat = match &token.token {
            Token::CommentLine(_) => unreachable!(),
            Token::Let => self.parse_let()?,
            Token::Return => self.parse_return()?,
            Token::Switch => self.parse_switch()?,
            Token::If => self.parse_if()?,
            Token::While => self.parse_while()?,
            Token::For => self.parse_for()?,
            Token::Break => {
                self.iter.next();
                Stat::Break
            }
            Token::Continue => {
                self.iter.next();
                Stat::Continue
            }
            Token::Const => self.parse_comptime_const()?,
            Token::Import => self.parse_import()?,
            Token::Func => self.parse_func(public)?,
            Token::Struct => self.parse_struct()?,
            Token::Enum => self.parse_enum()?,
            Token::Union => self.parse_union()?,
            _ => {
                let expr = self.parse_expr()?;

                match self.iter.peek() {
                    // A = B
                    Some(TokenPos {
                        token: Token::Cmp(CompareOperator::Eq),
                        pos: _,
                    }) => {
                        self.iter.next();
                        Stat::Assign {
                            target: expr,
                            value: self.parse_expr()?,
                        }
                    }
                    // A += B
                    Some(TokenPos {
                        token: Token::SelfArithmetic(op),
                        pos: _,
                    }) => {
                        let op = *op;
                        self.iter.next();
                        Stat::ComputeAssign {
                            op,
                            target: expr,
                            value: self.parse_expr()?,
                        }
                    }
                    _ => Stat::Expr(expr),
                }
            }
        };

        Ok(StatPos {
            comments: document,
            stat,
            pos: head_pos,
        })
    }

    fn parse_comment(&mut self) -> (Vec<String>, Pos) {
        let mut document = vec![];
        let mut doc_pos = Pos::zero();

        while let Some(TokenPos {
            token: Token::CommentLine(line),
            pos,
        }) = self.iter.peek()
        {
            if document.is_empty() {
                doc_pos = pos.clone();
            }

            document.push(line.clone());
            self.iter.next();
        }

        (document, doc_pos)
    }

    fn parse_return(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // return

        if let Some(TokenPos {
            token: Token::Void,
            pos: _,
        }) = self.iter.peek()
        {
            self.iter.next();
            Ok(Stat::Return(None))
        } else {
            let expr = self.parse_expr()?;
            Ok(Stat::Return(Some(expr)))
        }
    }

    fn parse_import(&mut self) -> Result<Stat, Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        if let Some(TokenPos {
            token: Token::String(path),
            pos: _,
        }) = self.iter.next()
        {
            Ok(Stat::Import(path))
        } else {
            Err(syntax_error("expect string after import", token.pos))
        }
    }

    /*
    while COND {
        STAT1
        STAT2
        STAT3
    }
    */
    fn parse_while(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // while

        let cond = self.parse_expr()?;

        self.expect_lbrace()?;
        let body = self.parse_stats_until_rbrace()?;

        Ok(Stat::While { cond, body })
    }

    /*
    for <index> = <iterator> {
        <body>...
    }
    */
    fn parse_for(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // for

        let (index, index_pos) = self.parse_ident()?;

        self.expect_equal()?; // =

        let iterator = self.parse_expr()?;

        self.expect_lbrace()?;

        let body = self.parse_stats_until_rbrace()?;

        Ok(Stat::For {
            index,
            index_ty: Type::Unknown,
            index_pos,
            iterator,
            body,
        })
    }

    fn parse_if(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // if

        let cond = self.parse_expr()?;

        self.expect_lbrace()?;
        let then = self.parse_stats_until_rbrace()?;

        let mut elif = vec![];
        while let Some(TokenPos {
            token: Token::Elif,
            pos: _,
        }) = self.iter.peek()
        {
            self.iter.next(); // elif

            let cond = self.parse_expr()?;

            self.expect_lbrace()?;

            let then = self.parse_stats_until_rbrace()?;

            elif.push(IfBranch { cond, then })
        }

        let mut otherwise = vec![];
        if let Some(TokenPos {
            token: Token::Else,
            pos: _,
        }) = self.iter.peek()
        {
            self.iter.next(); // else

            self.expect_lbrace()?;

            otherwise = self.parse_stats_until_rbrace()?;
        }
        Ok(Stat::If {
            head: IfBranch { cond, then },
            elif,
            otherwise,
        })
    }

    /*
    switch expr {
        V1: { }
        V2: { }
        else: { }
    }
    */
    fn parse_switch(&mut self) -> Result<Stat, Error> {
        self.iter.next();

        let expr = self.parse_expr()?;

        self.expect_lbrace()?;

        let mut branch = vec![];
        let mut default = vec![];
        let mut has_default = false;

        loop {
            let token = self.iter.next().ok_or(Error::Eof)?;

            let name = match token.token {
                Token::Rbrace => break,
                Token::Identifier(name) => Some(name),
                Token::Else => {
                    has_default = true;
                    None
                }
                _ => return Err(syntax_error("unexpected token at switch", token.pos)),
            };

            self.expect_colon()?; // :
            self.expect_lbrace()?; // {

            let stat = self.parse_stats_until_rbrace()?;

            match name {
                Some(name) => branch.push(SwitchBranch {
                    variant: name,
                    stat,
                }),
                None => {
                    default = stat;
                    self.expect_rbrace()?;
                    break;
                }
            }
        }

        Ok(Stat::Switch(Switch {
            head: Box::new(expr),
            branch,
            default,
            has_default,
        }))
    }

    // enum name {
    //   variant1
    //   variant2
    // }
    fn parse_enum(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // enum

        let (name, _) = self.parse_ident()?; // Name of enum

        self.expect_lbrace()?; // {

        let mut variants = vec![];

        loop {
            let (document, doc_pos) = self.parse_comment();

            let token = self.iter.next().ok_or(Error::Eof)?;
            match token.token {
                Token::Identifier(name) => {
                    variants.push(crate::item::EnumVariant {
                        inner: name,
                        comment: document,
                    });
                }
                Token::Rbrace => {
                    if !document.is_empty() {
                        return Err(Error::UnexpectedComment {
                            pos_desc: "end of all variants".into(),
                            pos: doc_pos,
                        });
                    }
                    break;
                }
                _ => {
                    return Err(syntax_error(
                        "expect ident or '}' in struct definition",
                        token.pos,
                    ));
                }
            }
        }

        Ok(Stat::Enum(Enum { name, variants }))
    }

    // struct name {
    //   arg1: type1
    //   arg2: type2
    // }
    fn parse_struct(&mut self) -> Result<Stat, Error> {
        self.iter.next();

        let (name, _) = self.parse_ident()?;

        self.expect_lbrace()?;

        let mut fields = vec![];

        loop {
            let (comment, pos) = self.parse_comment();

            let token = self.iter.next().ok_or(Error::Eof)?;
            match token.token {
                Token::Identifier(name) => {
                    self.expect_colon()?;

                    let ty = self.parse_type()?;

                    fields.push(WithComment {
                        inner: VarDecl {
                            name: name.clone(),
                            ty,
                        },
                        comment,
                    });
                }
                Token::Rbrace => {
                    if !comment.is_empty() {
                        return Err(Error::UnexpectedComment {
                            pos_desc: "end of all structs fields".into(),
                            pos,
                        });
                    }
                    break;
                }
                _ => {
                    return Err(syntax_error(
                        "expect ident or '}' in struct definition",
                        token.pos,
                    ));
                }
            }
        }
        Ok(Stat::Struct(Struct { name, fields }))
    }

    // union name {
    //   arg1: type1
    //   arg2: type2
    // }
    fn parse_union(&mut self) -> Result<Stat, Error> {
        self.iter.next();

        let (name, _) = self.parse_ident()?;

        self.expect_lbrace()?;

        let mut variants = vec![];

        loop {
            let (comment, pos) = self.parse_comment();

            let token = self.iter.next().ok_or(Error::Eof)?;
            match token.token {
                Token::Identifier(name) => {
                    self.expect_colon()?;

                    let ty = self.parse_type()?;

                    variants.push(WithComment {
                        inner: VarDecl {
                            name: name.clone(),
                            ty,
                        },
                        comment,
                    });
                }
                Token::Rbrace => {
                    if !comment.is_empty() {
                        return Err(Error::UnexpectedComment {
                            pos_desc: "end of all union fields".into(),
                            pos,
                        });
                    }
                    break;
                }
                _ => {
                    return Err(syntax_error(
                        "expect ident or '}' in union definition",
                        token.pos,
                    ));
                }
            }
        }

        Ok(Stat::Union(Union { name, variants }))
    }

    pub fn new(iter: Iter) -> Self {
        Self {
            iter: iter.peekable(),
        }
    }

    // let <name> = <value>
    // let <name> <type> = <value>
    fn parse_let(&mut self) -> Result<Stat, Error> {
        // let

        let token = self.iter.next().ok_or(Error::Eof)?;
        let Token::Let = token.token else {
            return Err(syntax_error(
                "expect 'let' to parse let statement",
                token.pos,
            ));
        };

        // name

        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Identifier(name) = token.token else {
            return Err(syntax_error("Expect variable name after 'let'", token.pos));
        };

        let head = self.iter.peek().ok_or(Error::Eof)?;

        if let Token::Cmp(CompareOperator::Eq) = head.token {
            // let name =
            debug!("let without type");

            self.iter.next(); // =
            let expr = self.parse_expr()?;

            Ok(Stat::Let(Let {
                decl: VarDecl {
                    name,
                    ty: Type::Unknown,
                },
                expr,
            }))
        } else {
            // let name: type
            debug!("let with type");

            self.expect_colon()?;

            let ty = self.parse_type()?;

            if let Some(TokenPos {
                token: Token::Cmp(CompareOperator::Eq),
                pos: _,
            }) = self.iter.peek()
            {
                // let name: type =
                self.iter.next(); // '='

                Ok(Stat::Let(Let {
                    decl: VarDecl { name, ty },
                    expr: self.parse_expr()?,
                }))
            } else {
                // let name: type
                Ok(Stat::LetUninit(VarDecl { name, ty }))
            }
        }
    }

    pub fn parse_type(&mut self) -> Result<Type, Error> {
        let head = self.iter.next().ok_or(Error::Eof)?;

        let mut ty = match &head.token {
            Token::Null => Type::Null,
            Token::Void => Type::Void,
            Token::Identifier(name) => ident_to_type(name, &head.pos)?,
            Token::Lsquace => self.parse_type_maker()?,
            _ => {
                return Err(Error::Syntax {
                    error: format!(
                        "can't understand token '{:?}' when parse a type",
                        head.token
                    ),
                    pos: head.pos.clone(),
                })
            }
        };

        loop {
            match self.iter.peek() {
                Some(TokenPos {
                    token: Token::Const,
                    pos: _,
                }) => {
                    self.iter.next();
                    ty = Type::Const(Box::new(ty))
                }
                Some(TokenPos {
                    token: Token::Star,
                    pos: _,
                }) => {
                    self.iter.next();
                    ty = Type::Pointer(Box::new(ty))
                }
                Some(TokenPos {
                    token: Token::Question,
                    pos: _,
                }) => {
                    self.iter.next();
                    ty = Type::OptionalPointer(Box::new(ty))
                }
                _ => break,
            }
        }

        Ok(ty)
    }

    // [...]
    fn parse_type_maker(&mut self) -> Result<Type, Error> {
        let head = self.iter.peek().ok_or(Error::Eof)?;

        match head.token {
            // Pointer type: [* TYPE]
            Token::Star => {
                self.iter.next();
                let inner = self.parse_type()?;
                self.expect_rsquace()?;
                Ok(Type::Pointer(Box::new(inner)))
            }
            Token::Question => {
                self.iter.next();
                let inner = self.parse_type()?;
                self.expect_rsquace()?;
                Ok(Type::OptionalPointer(Box::new(inner)))
            }
            // Const type: [const TYPE]
            Token::Const => {
                self.iter.next();
                let inner = self.parse_type()?;
                self.expect_rsquace()?;
                Ok(Type::Const(Box::new(inner)))
            }
            // Array type: [N TYPE]
            _ => {
                let length = self.parse_expr()?;
                let element_type = self.parse_type()?;

                self.expect_rsquace()?;
                Ok(Type::Array {
                    element_type: Box::new(element_type),
                    length: Box::new(length),
                })
            }
        }
    }

    fn parse_ident(&mut self) -> Result<(CowStr, Pos), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Identifier(name) = token.token else {
            return Err(syntax_error(
                format!("expect ident, find: {:?}", token.token),
                token.pos,
            ));
        };

        Ok((name, token.pos))
    }

    // Parse a function, call after consume 'func'.
    //
    // ```
    // func (NAME ARG1: TYPE1 ARG2: TYPE2 ...) TYPE {
    //    ...
    // }
    // ```
    fn parse_func(&mut self, public: bool) -> Result<Stat, Error> {
        self.iter.next(); // func

        self.expect_lpare()?; // (

        let (mut func_name, func_pos) = self.parse_ident()?;

        if self
            .iter
            .next_if(|token| {
                matches!(
                    token,
                    TokenPos {
                        token: Token::DColon,
                        pos: _
                    }
                )
            })
            .is_some()
        {
            let (method_name, _) = self.parse_ident()?;
            func_name = format!("{func_name}_{method_name}").into();
        }

        // func (<func_name> <args>...) {

        let mut paras = vec![];

        loop {
            let token = self.iter.peek().ok_or(Error::Eof)?;

            // End of arguments
            if let Token::Rpare = token.token {
                self.iter.next();
                break;
            }

            let (name, _) = self.parse_ident()?;

            self.expect_colon()?;

            let typ = self.parse_type()?;

            paras.push(VarDecl { name, ty: typ });
        }

        // func <name>(<arg>...) { <stat>... }
        // OR:
        // func <name>(<arg>...) <type> { <stat>... }

        let return_type = if let Some(TokenPos {
            token: Token::Lbrace,
            pos: _,
        }) = self.iter.peek()
        {
            Type::Void
        } else {
            self.parse_type()?
        };

        self.expect_lbrace()?;

        let stats = self.parse_stats_until_rbrace()?;

        if func_name == "main" {
            func_name = MC_MAIN_FUNC.into();

            if return_type != Type::Void || !paras.is_empty() || !public {
                return Err(Error::Syntax {
                    error: format!(
                        "main function of makec must be public, return void and accept no parameters"
                    ),
                    pos: func_pos,
                });
            }
        }

        Ok(Stat::Func(Func {
            public,
            return_type,
            paras,
            name: func_name,
            body: stats,
        }))
    }

    fn parse_stats_until_rbrace(&mut self) -> Result<Vec<StatPos>, Error> {
        let mut stats = vec![];

        loop {
            // Reach '}'
            if let Some(TokenPos {
                token: Token::Rbrace,
                pos: _,
            }) = self.iter.peek()
            {
                self.iter.next();
                break;
            }

            let stat = self.parse_stat()?;

            stats.push(stat);
        }
        Ok(stats)
    }

    fn expect_equal(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Cmp(CompareOperator::Eq) = token.token else {
            return Err(syntax_error("expect '='".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_lpare(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Lpare = token.token else {
            return Err(syntax_error("expect '('".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_colon(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Colon = token.token else {
            return Err(syntax_error("expect ':'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_dot(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Dot = token.token else {
            return Err(syntax_error("expect '.'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_rpare(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Rpare = token.token else {
            return Err(syntax_error("expect ')'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_rsquace(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Rsquace = token.token else {
            return Err(syntax_error("expect ']'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_lbrace(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Lbrace = token.token else {
            return Err(syntax_error("expect '{'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn expect_rbrace(&mut self) -> Result<(), Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        let Token::Rbrace = token.token else {
            return Err(syntax_error("expect '}'".to_owned(), token.pos));
        };

        Ok(())
    }

    fn parse_s_expr(&mut self) -> Result<Expr, Error> {
        let token = self.iter.next().ok_or(Error::Eof)?;

        debug!("parse expr after '(', next token: {token:?}");

        let ty = match token.token {
            // (& X)
            Token::Ampersand => {
                let expr = self.parse_expr()?;
                self.expect_rpare()?;

                Expr::TakeAddr(Box::new(expr))
            }
            // (. EXPR NAME)
            Token::Dot => {
                let expr = self.parse_expr()?;
                let (name, _) = self.parse_ident()?;
                self.expect_rpare()?;
                Expr::Get {
                    expr: Box::new(expr),
                    name,
                }
            }
            // ([] EXPR INDEX)
            Token::Lsquace => {
                self.expect_rsquace()?;
                let expr = self.parse_expr()?;
                let index = self.parse_expr()?;
                self.expect_rpare()?;
                Expr::Take {
                    expr: Box::new(expr),
                    index: Box::new(index),
                }
            }
            // (* expr)
            Token::Star => {
                let expr = self.parse_expr()?;
                self.expect_rpare()?;

                Expr::Dref(Box::new(expr))
            }
            // (op expr rest...)
            Token::Arithmetic(op) => {
                let expr = self.parse_expr()?;
                let rest = self.parse_exprs_until_rpare()?;

                Expr::Compute {
                    op,
                    head: Box::new(expr),
                    rest,
                }
            }
            // (and a b c ...)
            Token::And => {
                let head = self.parse_expr()?;
                let rest = self.parse_exprs_until_rpare()?;

                Expr::And {
                    head: Box::new(head),
                    rest,
                }
            }
            // (or a b c...)
            Token::Or => {
                let head = self.parse_expr()?;
                let rest = self.parse_exprs_until_rpare()?;

                Expr::Or {
                    head: Box::new(head),
                    rest,
                }
            }
            // (not cond)
            Token::Not => {
                let cond = Box::new(self.parse_expr()?);
                self.expect_rpare()?;

                Expr::Not { cond }
            }
            Token::BShl => {
                let expr = Box::new(self.parse_expr()?);
                let length = Box::new(self.parse_expr()?);
                self.expect_rpare()?;

                Expr::BShl { expr, length }
            }
            Token::BShr => {
                let expr = Box::new(self.parse_expr()?);
                let length = Box::new(self.parse_expr()?);
                self.expect_rpare()?;

                Expr::BShr { expr, length }
            }
            // (cast ty expr)
            Token::Cast => {
                let ty = self.parse_type()?;
                let expr = self.parse_expr()?;
                self.expect_rpare()?;

                Expr::Cast {
                    expr: Box::new(expr),
                    ty,
                }
            }
            // (sizeof ty)
            Token::Sizeof => {
                let ty = self.parse_type()?;
                self.expect_rpare()?;

                Expr::Sizeof { ty }
            }
            // (CMP a b)
            Token::Cmp(cmp) => {
                let lhs = self.parse_expr()?;
                let rhs = self.parse_expr()?;
                self.expect_rpare()?;
                Expr::Compare {
                    cmp,
                    lhs: Box::new(lhs),
                    rhs: Box::new(rhs),
                }
            }
            // (if cond1: val1
            //     cond2: val2
            //     else: else_val)
            Token::If => self.parse_if_cond()?,
            Token::Identifier(func) => self.parse_func_call(func)?,
            _ => {
                return Err(Error::Syntax {
                    error: format!("can't parse token after '(', token: {token:?}"),
                    pos: token.pos,
                })
            }
        };

        Ok(ty)
    }

    fn parse_func_call(&mut self, mut func: CowStr) -> Result<Expr, Error> {
        let is_macro = self
            .iter
            .next_if(|token| token.token == Token::Not)
            .is_some();

        if self
            .iter
            .next_if(|token| {
                matches!(
                    token,
                    TokenPos {
                        token: Token::DColon,
                        pos: _
                    }
                )
            })
            .is_some()
        {
            let (name, _) = self.parse_ident()?;
            func = format!("{func}_{name}").into();
        }

        let args = self.parse_exprs_until_rpare()?;

        Ok(Expr::Call(Call {
            is_macro,
            is_method: false,
            func,
            args,
        }))
    }

    fn parse_if_cond(&mut self) -> Result<Expr, Error> {
        let mut branch = vec![];
        let cond;
        loop {
            if let Some(TokenPos {
                token: Token::Else,
                pos: _,
            }) = self.iter.peek()
            {
                self.iter.next(); // else
                self.expect_colon()?; // :
                let otherwise = Box::new(self.parse_expr()?);
                self.expect_rpare()?; // )

                cond = Expr::IfExpr(IfExpr { branch, otherwise });
                break;
            }

            let cond = self.parse_expr()?;
            self.expect_colon()?;
            let val = self.parse_expr()?;
            branch.push((cond, val));
        }
        Ok(cond)
    }

    // a b c...)
    fn parse_exprs_until_rpare(&mut self) -> Result<Vec<ExprPos>, Error> {
        let mut rest = vec![];

        loop {
            if let Some(TokenPos {
                token: Token::Rpare,
                pos: _,
            }) = self.iter.peek()
            {
                self.iter.next();
                break;
            }

            rest.push(self.parse_expr()?);
        }

        Ok(rest)
    }

    fn parse_comptime_const(&mut self) -> Result<Stat, Error> {
        self.iter.next(); // const

        let (name, _) = self.parse_ident()?;

        self.expect_equal()?;

        let expr = self.parse_expr()?;
        let expr_display = format!("{}", ExprC::new(&expr.expr, 0));

        Ok(Stat::ComptimeConstant {
            decl: VarDecl {
                name,
                ty: Type::Unknown,
            },
            expr,
            expr_display,
        })
    }
}

fn ident_to_type(name: &CowStr, pos: &Pos) -> Result<Type, Error> {
    let ty = match name.as_ref() {
        "int" => Type::Int,
        "uint" => Type::UInt,

        "int32" => Type::Int32,
        "int64" => Type::Int64,
        "uint32" => Type::Uint32,
        "uint64" => Type::Uint64,

        "char" => Type::Char,

        "void" => Type::Void,
        "bool" => Type::Boolean,

        _ => {
            if !name
                .chars()
                .next()
                .map(|c| c.is_ascii_uppercase())
                .unwrap_or_default()
            {
                return Err(Error::Syntax {
                    error: format!("custom type name must starts with uppercase: {name}"),
                    pos: pos.clone(),
                });
            }

            Type::Ref { name: name.clone() }
        }
    };

    Ok(ty)
}

impl From<i64> for Expr {
    fn from(val: i64) -> Self {
        Expr::I64(val)
    }
}
